/*==============================================================================
**                                  STM32BOOT
**                      Proprietary - Copyright (C) 2014
**------------------------------------------------------------------------------
** Supported MCUs      : MCU STM32
** Supported Compilers : KeilC
**------------------------------------------------------------------------------
** File name         : Fls.c
**  
** Module name       : Flash Driver
**
** Summary: Flash Programming Functions adapted for 
**          ST Microelectronics STM32F3xx Flash 
**
**= History ===================================================================
** 00.00.01  7/1/2014  Cuong Chu
** - Creation
==============================================================================*/
/******************************************************************************/
/* INCLUSIONS                                                                 */
/******************************************************************************/
#include "..\Fls.h"
/******************************************************************************/
/* DEFINITION OF TYPES                                                        */
/******************************************************************************/
typedef volatile unsigned short   vu16;
typedef          unsigned short    u16;
typedef volatile unsigned long    vu32;
typedef          unsigned long     u32;
/******************************************************************************/
/* DEFINITION OF MACROS                                                       */
/******************************************************************************/
#define M16(adr) (*((vu16 *) (adr)))
#define M32(adr) (*((vu32 *) (adr)))
/* Peripheral Memory Map */
/* Flash */
#define FLASH_BASE      0x40022000
#define FLASH           ((FLASH_TypeDef*) FLASH_BASE)
/* Flash Registers */
typedef struct {
  vu32 ACR;                                     /* offset  0x000 */
  vu32 KEYR;                                    /* offset  0x004 */
  vu32 OPTKEYR;                                 /* offset  0x008 */
  vu32 SR;                                      /* offset  0x00C */
  vu32 CR;                                      /* offset  0x010 */
  vu32 AR;                                      /* offset  0x014 */
  vu32 RESERVED0[1];
  vu32 OBR;                                     /* offset  0x01C */
  vu32 WRPR;                                    /* offset  0x020 */
} FLASH_TypeDef;
/* Flash Keys */
#define RDPRT_KEY       0x55AA
#define FLASH_KEY1      0x45670123
#define FLASH_KEY2      0xCDEF89AB
/* Flash Control Register definitions */
#define FLASH_PG                ((unsigned int)(1ul << 0))
#define FLASH_PER               ((unsigned int)(1ul << 1))
#define FLASH_MER               ((unsigned int)(1ul << 2))
#define FLASH_OPTPG             ((unsigned int)(1ul << 4))
#define FLASH_OPTER             ((unsigned int)(1ul << 5))
#define FLASH_STRT              ((unsigned int)(1ul << 6))
#define FLASH_LOCK              ((unsigned int)(1ul << 7))
#define FLASH_OPTWRE            ((unsigned int)(1ul << 9))
/* Flash Status Register definitions */
#define FLASH_BSY               ((unsigned int)(1ul << 0))
#define FLASH_PGERR             ((unsigned int)(1ul << 2))
#define FLASH_WRPRTERR          ((unsigned int)(1ul << 4))
#define FLASH_EOP               ((unsigned int)(1ul << 5))
#define FLASH_ERR               (FLASH_PGERR | FLASH_WRPRTERR)
/******************************************************************************/
/* DEFINITION OF GLOBAL FUNCTIONS                                             */
/******************************************************************************/
/*******************************************************************************
** Function name: Fls_Unlock( uint32_t Address, uint32_t Clock, 
**                                 Fls_FunctionCodeType FunctionCode)
** Description  : The function called to unlock flash
** Parameter    : Address - Device Base Address
**                Clock   - Frequency of Clock System
**                FunctionCode - Select function for erase, program or verify
** Return value : None
** Remarks      : Called by IF_FLASH
*******************************************************************************/
void Fls_Unlock
( 
  uint32_t             Address, 
  uint32_t             Clock,
  Fls_FunctionCodeType FunctionCode
)
{
  /* Unlock Flash */
  FLASH->KEYR = FLASH_KEY1;                             
  FLASH->KEYR = FLASH_KEY2;
  /* Zero Wait State, no Cache, no Prefetch */
  FLASH->ACR  = 0x00000000;                             
  /* Reset Error Flags */
  FLASH->SR  |= FLASH_ERR;                              
}
/*******************************************************************************
** Function name: Fls_Lock(Fls_FunctionCodeType FunctionCode)
** Description  : The function called for lock flash
** Parameter    : FunctionCode - Select function for erase, program or verify
** Return value : None
** Remarks      : Called by IF_FLASH
*******************************************************************************/
void Fls_Lock
(
  Fls_FunctionCodeType FunctionCode
)
{
  /* Lock Flash */
  FLASH->CR |=  FLASH_LOCK;                             
}
/*******************************************************************************
** Function name: Fls_EraseSector(uint32_t Address)
** Description  : The function called for erase sector selected
** Parameter    : Address    - Sector Address
** Return value : FLS_OK     - if erase success
**                FLS_FAILED - if erase fail
** Remarks      : Called by IF_FLASH
*******************************************************************************/
Fls_ReturnType Fls_EraseSector
(
  uint32_t Address
)
{
  /* Page Erase Enabled  */
  FLASH->CR  |=  FLASH_PER;                          
  /* Page Address */
  FLASH->AR   =  Address;                                
  /* Start Erase */
  FLASH->CR  |=  FLASH_STRT;                           
  while (FLASH->SR  & FLASH_BSY) 
  {
    ;                              
  }
  /* Page Erase Disabled  */
  FLASH->CR  &= ~FLASH_PER;                           
  return FLS_OK;
}
/*******************************************************************************
** Function name: Fls_ProgramPage(uint32_t Address, uint32_t PageSize, 
**                                uint8_t* DataPtr)
** Description  : The function called for program data to on chip flash
** Parameter    : Address      - Page Start Address
**                ProgramSize  - Size of data program
**                DataPtr      - Point to Data write
** Return value: FLS_OK     - if program success
**               FLS_FAILED - if program fail
** Remarks: Called by IF_FLASH
*******************************************************************************/
Fls_ReturnType Fls_ProgramPage
(
  uint32_t Address, 
  uint32_t ProgramSize, 
  uint8_t  *DataPtr
)
{
  Fls_ReturnType retVal = FLS_OK;
  /* Adjust size for Half Words */
  ProgramSize = (ProgramSize + 1) & ~1;                                   
  while (ProgramSize) 
  {
    /* Programming Enabled */
    FLASH->CR  |=  FLASH_PG;                            
    /* Program Half Word */
    M16(Address) = *((u16 *)DataPtr);                           
    while (FLASH->SR  & FLASH_BSY);
    /* Programming Disabled */
    FLASH->CR  &= ~FLASH_PG;                            
    /* Check for Error */
    if (FLASH->SR & FLASH_ERR) 
    {                        
      /* Reset Error Flags */
      FLASH->SR |= FLASH_ERR;                           
      ProgramSize = 0;
      retVal = FLS_FAILED;
    }
    else
    {
      /* Go to next Half Word */
      Address += 2;                                           
      DataPtr += 2;
      ProgramSize  -= 2;
    }
  }
  return retVal;
}
/*******************************************************************************/
/*                      End of File                                            */
/*******************************************************************************/
